﻿using System.Diagnostics;
using RaytracerLib.MathLib;
using YAXLib;
using System;

namespace RaytracerLib
{
    public abstract class SceneActor : SceneElement
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        [YAXNode("Pos")]
        private Vector3 m_pos = Vector3.ZERO;

        public AABB BoundBox { get; protected set; }

        public virtual void Transform(Matrix4 a_transform)
        {
            m_pos = a_transform * Pos;
        }

        public virtual Vector3 Pos
        {
            get
            {
                return m_pos;
            }
            set
            {
                m_pos = value;
                Update(UpdateFlags.BoundBox | UpdateFlags.Matrices);
            }
        }

        public virtual void RotateAround(Vector3 a_point, Vector3 a_vector, double a_angle)
        {
            m_pos = (Matrix4.CreateTranslation(a_point) *
                     Matrix4.CreateRotateAroundVector(a_vector, a_angle) *
                     Matrix4.CreateTranslation(-a_point)) * Pos;
        }

        public void Translate(Vector3 a_t)
        {
            Pos += a_t;
        }

        [YAXOnDeserialized]
        private void OnDeserialized()
        {
            Update(UpdateFlags.All);
        }

        protected virtual AABB GetLocalBoundBox()
        {
            return AABB.POINT;
        }

        protected virtual AABB GetBoundBox()
        {
            AABB local_aabb = GetLocalBoundBox();
            return new AABB(Pos + local_aabb.Minimum, Pos + local_aabb.Maximum);
        }

        protected virtual void Update(UpdateFlags a_flags)
        {
            if (a_flags.HasFlag(UpdateFlags.BoundBox))
                BoundBox = GetBoundBox();
        }

        public virtual void ScaleAbsolute(double a_scale)
        {
            Pos = Pos * a_scale;

            Update(UpdateFlags.BoundBox | UpdateFlags.Matrices | UpdateFlags.Vertices);
        }
    }
}